package Montecarlo.Servidor.randomX;

/**
 * Abstract superclass for emulations of java.util.Random with various
 * underlying generators. These generators provide a superset of the methods of
 * the built-in Java generator, and allow easy replacement of the low-level
 * byte-stream random generator without the need to reimplement the higher-level
 * calls.
 * <p>
 * The nature of the data returned by the functions in this class depends upon
 * the generator provided by the class derived from it. If the generator is
 * algorithmic, the data are pseudorandom; if a hardware generator is employed,
 * genuine random data may be obtained. For brevity, in this document, we use
 * <em>random</em> to refer to the data returned, whatever its actual source.
 * <p>
 * Designed and implemented in July 1996 by <a
 * href="http://www.fourmilab.ch/">John Walker</a>.
 * 
 * @see java.util.Random
 */

public abstract class randomX {

	private int nbits = 0;
	private boolean iset = false;

	private double gset;

	private byte b;

	/*
	 * Emulation of standard java.util.Random methods. Given an implementation
	 * of nextByte() in the derived class, these methods provide all the other
	 * forms of results. A derived class is, of course, free to reimplement any
	 * of these. For example, a generator which produces 31 high-quality
	 * pseudorandom bits on each call might reimplement nextBit(), nextShort(),
	 * and nextFloat() to avoid the inefficiency of passing individual bytes to
	 * the parent class, then reassembling to return to the caller.
	 */

	/** @return the next random bit, as a <tt>boolean</tt>. */

	public boolean nextBit() {
		boolean bit;

		if (nbits <= 0) {
			b = nextByte();
			nbits = 8;
		}
		bit = (b & 0x80) != 0;
		b <<= 1;
		nbits--;
		return bit;
	}

	/**
	 * Return next [pseudo]random byte from low level generator. All generators
	 * derived from this class must implement <tt>nextByte()</tt>.
	 */

	public abstract byte nextByte();

	/**
	 * Fill an array of bytes with random data.
	 * 
	 * @param buf
	 *            array of <tt>byte</tt>s to fill.
	 */

	public void nextByte(byte buf[]) {
		nextByte(buf, buf.length);
	}

	/**
	 * Fill a portion of an array of bytes with random data.
	 * 
	 * @param buf
	 *            array of <tt>byte</tt> to fill.
	 * @param buflen
	 *            number of bytes to store.
	 */

	public void nextByte(byte buf[], int buflen) {
		int i = 0;

		while (buflen-- > 0) {
			buf[i++] = nextByte();
		}
	}

	/**
	 * @return the next random, uniformly distributed, <tt>double</tt> value,
	 *         greater than or equal to 0 and less than 1.
	 */

	public double nextDouble() {
		return (double) ((nextLong() & 0x7FFFFFFFFFFFFFFFl) / (0x7FFFFFFFFFFFFFFFl * 1.0));
	}

	/**
	 * @return the next random, uniformly distributed, <tt>float</tt> value,
	 *         greater than or equal to 0 and less than 1.
	 */

	public float nextFloat() {
		return (float) ((nextInt() & 0x7FFFFFFF) / (0x7FFFFFFF * 1.0));
	}

	// Extended generator access methods with default implementations

	/**
	 * @return the next Gaussian (normal, or bell-curve) distributed random
	 *         value, with mean of 0.0 and standard deviation 1.0.
	 */

	public double nextGaussian() {
		double fac, rsq, v1, v2;

		if (!iset) {
			do {
				v1 = 2 * nextDouble() - 1;
				v2 = 2 * nextDouble() - 1;
				rsq = v1 * v1 + v2 * v2;
			} while (rsq > 1.0 || rsq == 0.0);
			fac = Math.sqrt(-2.0 * Math.log(rsq) / rsq);
			gset = v1 * fac;
			iset = true;
			return v2 * fac;
		} else {
			iset = false;
			return gset;
		}
	}

	/**
	 * @return the next random, uniformly distributed, <tt>int</tt> value.
	 */

	public int nextInt() {
		return (int) ((((int) nextShort()) << 16) | (((int) nextShort()) & 0xFFFF));
	}

	/**
	 * @return the next random, uniformly distributed, <tt>long</tt> value.
	 */

	public long nextLong() {
		return (long) ((((long) nextInt()) << 32) | (((long) nextInt()) & 0xFFFFFFFFl));
	}

	/**
	 * @return the next random, uniformly distributed, <tt>short</tt> value.
	 */

	public short nextShort() {
		return (short) ((((short) nextByte()) << 8) | ((short) (nextByte() & 0xFF)));
	}

	/**
	 * Reset when seed changes. A generator which supports seed must call this
	 * method by <tt>super.setSeed()</tt> when its own <tt>setSeed(</tt>
	 * <i>long</i><tt>)</tt> method is called. This allows randomX to discard
	 * any buffered data in the <tt>nextBit()</tt> and <tt>nextGaussian()</tt>
	 * methods so that subsequent calls will immediately reflect the new seed.
	 * 
	 * <p>
	 * If a derived class does not permit specification of a seed
	 * (hardware-based generators, for example), it should declare:
	 * 
	 * <p>
	 * <blockquote> <tt>private void setSeed(long seed) { }</tt> </blockquote>
	 * <p>
	 * which will hide the setSeed method from its users and cause a
	 * compile-time error if a program attempts to specify a seed.
	 */

	public void setSeed() {
		nbits = 0;
		iset = false;
	}
}
